<?php
declare(strict_types=1);

namespace Initiating\Aspect;

use Swoft\Aop\Annotation\Mapping\Aspect;

use Swoft\Aop\Annotation\Mapping\PointAnnotation;
use Initiating\Annotation\Mapping\GloablTransaction;
use Initiating\TransactionResources\TxTransaction;
use Swoft\Aop\Annotation\Mapping\Around;
use Swoft\Aop\Point\ProceedingJoinPoint;
use Swoft\Bean\Annotation\Mapping\Inject;
use Initiating\AnnotationData\AnnotationData;
use UntilDistributed\TxId;
use Swoole\Coroutine;

/**
 * 分布式事务切面
 * @Aspect(order=1)
 * @PointAnnotation(
 *     include={GloablTransaction::class}
 * )
 * @author mg
 */
class TransactionAspect
{
	/**
	 * @Inject()
	 * @var TxTransaction
	 */
	private $transaction;
	
	
	/**
	 * @Around()
	 *
	 * @param ProceedingJoinPoint $proceedingJoinPoint
	 *
	 * @return mixed
	 */
	public function around(ProceedingJoinPoint $proceedingJoinPoint)
	{
		
		$className = get_class($proceedingJoinPoint->getTarget());
		
		$className = substr($className, 0, strpos($className, '_'));
		
		/**
		 * @var GloablTransaction $gloablTransaction
		 */
		$gloablTransaction = AnnotationData::get($className);
		
		if (!$gloablTransaction) {
			throw new \Exception("没有找到切面注解对象");
		}
		
		$this->transaction->initTxGroup();
		
		$this->transaction->addTxGroupAndSetTimeOut($gloablTransaction->getTimeout());
		
		TxId::getInstance()->push($this->transaction->getTransGroup()->groupId, $gloablTransaction->getActorNumber());
		
		// Before around
		$result = $proceedingJoinPoint->proceed();
		
		TxId::getInstance()->clear();
		// After around
		
		if (!$result) {
			return $result;
		}
		
		if (0 === $result['status']) {
			return $result;
		}
		
		$this->transaction->submittedByTheInitiator();
		
		Coroutine::create(function(TxTransaction $tx){
			
			Coroutine::sleep(2);
			
			$tx->getTxClientManage()->getSwooleClient()->close();
			
		}, $this->transaction);
		
		return $result;
	}
	
}